/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package ca.usask.cs.decisiontree.DOTHandler;

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.util.ArrayList;
import java.util.Collections;

import javax.swing.JOptionPane;

import ca.usask.cs.decisiontree.*;
import ca.usask.cs.decisiontree.api.EventEdgeInterface;
import ca.usask.cs.decisiontree.api.DecisionNodeInterface;
import ca.usask.cs.decisiontree.api.Edge;
import ca.usask.cs.decisiontree.api.TreeNode;

/**
 * 
 * @author Administrator
 */
public class WriteDOT {

	BufferedWriter out;

	public boolean write(String fileName, DecisionTree tree, ArrayList nodeList, ArrayList edgeList, ArrayList timeList)
    {
        try{
            // Create file
            FileWriter fstream = new FileWriter(fileName);
            BufferedWriter out = new BufferedWriter(fstream);
            out.write(setup());
            out.write(parseTimeLine(timeList));
            out.write(parseNodeList(nodeList));
            out.write(parseEdgeList(edgeList));
            out.write(parseTree(tree));

            //Close the output stream
            out.close();
            return true;
        }
        catch (Exception e){//Catch exception if any    	
        	JOptionPane.showMessageDialog(null, "Error: " + e.getMessage());
        //  System.err.println("Error: " + e.getMessage());
          return false;
        }
    }

	/**
	 * setup the initial dot file
	 */
	public String setup() {
		String dot;
		dot = "digraph OsgoodDecisionTree {";
		dot = dot + "\nsize=\"7,8\"; ";
		return dot;
	}

	/**
	 * create the timeline in dot
	 * 
	 * @param timeList
	 */
	public String parseTimeLine(ArrayList timeList) {
		String dot = "";

		Collections.sort(timeList);
		for (int i = 0; i < timeList.size(); i++) {
			dot = dot + "\nnode [fontsize=24, shape = plaintext];";
			dot = dot + "\n" + timeList.get(i) + ";";
		}
		dot = dot + "\nedge [style=invis];\n";

		for (int i = 0; i < timeList.size(); i++) {
			// if the last item don't print the arrow
			if (i == (timeList.size() - 1)) {
				dot = dot + timeList.get(i) + ";";
			} else {
				dot = dot + timeList.get(i) + "->";
			}
		}
		return dot;
	}

	/**
	 * parses the information of the tree to dot
	 * 
	 * @param tree
	 *            - the decisiontree
	 */
	public String parseTree(DecisionTree tree) {
		String dot = "";

		dot = "\nlabel=\"ID=" + tree.getTreeID() + " " + tree.getTreeName()
				+ "\" fontsize=45;\n}";

		return dot;
	}

	/**
	 * parses each node to dot
	 * 
	 * @param nodeList
	 *            - list of nodes
	 */
	public String parseNodeList(ArrayList nodeList) {
		String dot = "\nedge [style=vis];";

		for (int i = 0; i < nodeList.size(); i++) {
			TreeNode curNode = (TreeNode) nodeList.get(i);
			// parse a chance node
			if (curNode.getNodeType().equals("DecisionNode")) {
				dot = dot
						+ "\nnode [height=2, width=2, style=filled, color=blue, fontsize=12, shape = box, ";
				dot = dot + "label=\"ID=" + curNode.getTreeNodeID();
				dot = dot + "\\n" + curNode.getVariableName();
				dot = dot + "\\n(" + curNode.getRollBackValue() + ")\"];";
				dot = dot + "{ rank = same; " + curNode.getTime() + " N"
						+ curNode.getTreeNodeID() + "; }";
			}
			// parse a decision node
			else if (curNode.getNodeType().equals("ChanceNode")) {
				dot = dot
						+ "\nnode [fontsize=12, style=filled,color=green, shape = circle, ";
				dot = dot + "label=\"ID=" + curNode.getTreeNodeID();
				dot = dot + "\\n" + curNode.getVariableName();
				dot = dot + "\\n(" + curNode.getRollBackValue() + ")\"];";
				dot = dot + "{ rank = same; " + curNode.getTime() + " N"
						+ curNode.getTreeNodeID() + "; }";
			}
			// parse a terminal node
			else if (curNode.getNodeType().equals("TerminalNode")) {
				dot = dot
						+ "\nnode [fontsize=12, style=filled,color=red, shape = triangle, ";
				dot = dot + "label=\"ID=" + curNode.getTreeNodeID();
				dot = dot + "\\n" + curNode.getVariableName();
				dot = dot + "\\n(" + curNode.getRollBackValue() + ")\"];";
				dot = dot + "{ rank = same; " + curNode.getTime() + " N"
						+ curNode.getTreeNodeID() + "; }";
			}

		}

		return dot;
	}

	/**
	 * parses each edge to dot
	 * 
	 * @param edgeList
	 *            - list of edges
	 */
	public String parseEdgeList(ArrayList edgeList) {
		String dot = "";

		for (int i = 0; i < edgeList.size(); i++) {
			Edge curEdge = (Edge) edgeList.get(i);
			int sourceID = curEdge.getSourceNode().getTreeNodeID();
			int destID = curEdge.getDestinationNode().getTreeNodeID();
			int edgeID = curEdge.getEdgeID();

			// parse a chance edge
			if (curEdge.getEdgeType().equals("ChanceEdge")) {
				EventEdgeInterface curChanceEdge = (EventEdgeInterface) curEdge;

				// C3 -> T4 [color=red,label="ID=8\n{0.6*(.6)}"];
				dot = dot + "\nN" + sourceID + " -> N" + destID
						+ "[label=\"ID=";
				dot = dot + edgeID + "\\nv=" + curChanceEdge.getValue();
				dot = dot + "\\np=" + curChanceEdge.getProbability() + "\"];";
			}
			// parse a regular edge
			else {
				DecisionNodeInterface sourceNode = (DecisionNodeInterface) curEdge
						.getSourceNode();
				Edge bestChildEdge = sourceNode.getBestChildEdge();

				// if the edge is the best child
				if (curEdge == bestChildEdge) {
					dot = dot + "\nN" + sourceID + " -> N" + destID
							+ "[color=red,arrowsize=3, label=\"ID=";
					dot = dot + edgeID + "\\n(" + curEdge.getValue() + ")\"];";
				}
				// normal edge
				else {
					// D2 -> T6 [label="ID=10\n{0.3}"];
					dot = dot + "\nN" + sourceID + " -> N" + destID
							+ "[label=\"ID=";
					dot = dot + edgeID + "\\n(" + curEdge.getValue() + ")\"];";
				}
			}
		}
		return dot;
	}

}
